package com.ingenico.insider.services.impl;

import java.awt.FlowLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.logging.Logger;

import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextField;

import com.ingenico.insider.swing.ZoomFitAction;
import com.ingenico.insider.swing.ZoomHeightAction;
import com.ingenico.insider.swing.ZoomInAction;
import com.ingenico.insider.swing.ZoomOneAction;
import com.ingenico.insider.swing.ZoomOutAction;
import com.ingenico.insider.swing.ZoomSetAction;
import com.ingenico.insider.swing.ZoomWidthAction;
import com.ingenico.insider.util.Constants;

import edu.umd.cs.piccolo.PCamera;

public final class ZoomControlSupplier {
	private static final Logger _logger = Logger.getLogger(ZoomControlSupplier.class.getCanonicalName()); 

	/**
	 * Public constant keywords
	 */
	public static final String SCALE_KEY = "scale";
	public static final String ZOOM_KEY = "zoom";
	public static final String SEPARATOR = Constants.SEPARATOR;
	public static final String SCALE_ZOOMIN_KEY     = SCALE_KEY + SEPARATOR + ZOOM_KEY + SEPARATOR + "in";
	public static final String SCALE_ZOOMOUT_KEY    = SCALE_KEY + SEPARATOR + ZOOM_KEY + SEPARATOR + "out";
	public static final String SCALE_ZOOMONE_KEY    = SCALE_KEY + SEPARATOR + ZOOM_KEY + SEPARATOR + "one";
	public static final String SCALE_ZOOMSET_KEY    = SCALE_KEY + SEPARATOR + ZOOM_KEY + SEPARATOR + "set";
	public static final String SCALE_ZOOMFIT_KEY    = SCALE_KEY + SEPARATOR + ZOOM_KEY + SEPARATOR + "fit";
	public static final String SCALE_ZOOMWIDTH_KEY  = SCALE_KEY + SEPARATOR + ZOOM_KEY + SEPARATOR + "width";
	public static final String SCALE_ZOOMHEIGHT_KEY = SCALE_KEY + SEPARATOR + ZOOM_KEY + SEPARATOR + "height";

	/**
	 * singleton instance
	 */
	private static ZoomControlSupplier instance;

	private final class CameraScaleListener implements PropertyChangeListener {
		@Override
		public void propertyChange(PropertyChangeEvent e) {
			final Object eventSource = e.getSource();

			if (eventSource instanceof PCamera) {
				final PCamera sourceCamera = (PCamera)eventSource; 
				final String propertyName = e.getPropertyName();
				if (PCamera.PROPERTY_VIEW_TRANSFORM.equals(propertyName)) {
					zoomXText.setText(String.valueOf(sourceCamera.getViewScaleX()));
					zoomYText.setText(String.valueOf(sourceCamera.getViewScaleY()));
				}
			}
		}
	};

	private final JPanel zoomPanel;
	private final JTextField zoomXText;
	private final JTextField zoomYText;

	private final Action zoomInAction;
	private final Action zoomOutAction;
	private final Action zoomOneAction;
	private final Action zoomSetAction;
	private final Action zoomFitAction;
	private final Action zoomWidthAction;
	private final Action zoomHeightAction;

	private void initMenu() {
		final JMenu displayMenu = StandardMenuSupplier.getInstance().getDisplayMenu();
		final Action[] actions = new Action[] {
			zoomInAction,
			zoomOutAction,
			zoomOneAction,
			zoomFitAction,
			zoomWidthAction,
			zoomHeightAction
		};

		JMenuItem currentMenuItem;

		// Loop to init all file menu items at once and register them with a single action handler
		if (displayMenu.getItemCount() > 0) {
			displayMenu.addSeparator();
		}
		for (int i = 0; i < actions.length; i++) {
			currentMenuItem = new JMenuItem();
			currentMenuItem.setAction(actions[i]);
			displayMenu.add(currentMenuItem);
		}
	}

	private void initContainer() {
		zoomPanel.setLayout(new FlowLayout());

		final JButton zoomIn  = new JButton();
		final JButton zoomOut = new JButton();
		final JButton zoomOne = new JButton();
		final JButton zoomFit = new JButton();
		final JButton zoomWidth = new JButton();
		final JButton zoomHeight = new JButton();
		final JButton zoomSet = new JButton();

		zoomIn.setAction(zoomInAction);
		zoomOut.setAction(zoomOutAction);
		zoomOne.setAction(zoomOneAction);
		zoomSet.setAction(zoomSetAction);
		zoomFit.setAction(zoomFitAction);
		zoomWidth.setAction(zoomWidthAction);
		zoomHeight.setAction(zoomHeightAction);

		zoomIn.setText(null);
		zoomOut.setText(null);
		zoomOne.setText(null);
		zoomFit.setText(null);
		zoomWidth.setText(null);
		zoomHeight.setText(null);

		zoomPanel.add(zoomIn);
		zoomPanel.add(zoomOut);
		zoomPanel.add(zoomOne);
		zoomPanel.add(zoomWidth);
		zoomPanel.add(zoomHeight);
		zoomPanel.add(zoomFit);
		zoomPanel.add(zoomSet);
		zoomPanel.add(zoomXText);
		zoomPanel.add(new JLabel(":"));
		zoomPanel.add(zoomYText);

		final PCamera camera = CanvasSupplier.getInstance().getCanvas().getCamera();
		zoomXText.setText(String.valueOf(camera.getViewScaleX()));
		zoomYText.setText(String.valueOf(camera.getViewScaleY()));
		camera.addPropertyChangeListener(new CameraScaleListener());
	}
	
	/**
	 * private constructor of final class to prevent external instantiation
	 */
	private ZoomControlSupplier() {
		// Create actions
		zoomInAction  = LocalisationSupplier.getInstance().localize(new ZoomInAction(), SCALE_ZOOMIN_KEY);
		zoomOutAction = LocalisationSupplier.getInstance().localize(new ZoomOutAction(), SCALE_ZOOMOUT_KEY);
		zoomOneAction = LocalisationSupplier.getInstance().localize(new ZoomOneAction(), SCALE_ZOOMONE_KEY);
		zoomSetAction = LocalisationSupplier.getInstance().localize(new ZoomSetAction(), SCALE_ZOOMSET_KEY);
		zoomFitAction = LocalisationSupplier.getInstance().localize(new ZoomFitAction(), SCALE_ZOOMFIT_KEY);
		zoomWidthAction = LocalisationSupplier.getInstance().localize(new ZoomWidthAction(), SCALE_ZOOMWIDTH_KEY);
		zoomHeightAction = LocalisationSupplier.getInstance().localize(new ZoomHeightAction(), SCALE_ZOOMHEIGHT_KEY);

		// Create container
		zoomPanel = new JPanel();
		zoomXText = new JTextField();
		zoomYText = new JTextField();
		initContainer();

		initMenu();

		DockableViewsSupplier.getInstance().add(zoomPanel, SCALE_KEY);
	}

	/**
	 * retrieve the singleton instance
	 *
	 * @return the ZoomControlSupplier singleton
	 */
	public static ZoomControlSupplier getInstance() {
		if (instance == null) {
			_logger.info(ZoomControlSupplier.class.getName() + " instance does not exist... Creating instance.");
			instance = new ZoomControlSupplier();
		}
		return instance;
	}
	
	public String getScaleYText() {
		return zoomYText.getText();
	}

	public String getScaleXText() {
		return zoomXText.getText();
	}
}
